﻿using System;
using System.Collections;
using AgateLib.Sprites;
using AiAsteriods.Game.Entities.Base;
using AiAsteriods.Game.State;

namespace AiAsteriods.Game.Entities.Effects {
  class Emitter : EntityAbstract {
    private Random random;
    private Boolean sprayerOn = true;
    private int maxToMakePerSecond = 5;
    private int sprayThickness = 1;
    private double spraySpeed = 1;
    private double spraySpeedVariance = 0;
    public double SprayDirection { get; set; }
    private double sprayDirectionSpread = 0;
    private int emitTime = 0;
    private int particleLifeTime = 0;
    private int particleLifeTimeVariance = 0;

    public Boolean done { get; set; }
    private ArrayList sprays;

    public Emitter(Sprite s, int x, int y, double speed, double rotation, double collisionRadius, int collisionDamage,
                   int sprayThickness, double spraySpeed, double spraySpeedVariance, double sprayDirection,
                   double sprayDirectionSpread, int emitTime1, int particleLifeTime, int particleLifeTimeVariance,
                   int red, int green, int blue, GameStateAbstract state)
      : base(s, x, y, rotation, speed, collisionRadius, collisionDamage, 0, state) {
      done = false;

      this.particleLifeTimeVariance = particleLifeTimeVariance;
      this.spraySpeed = spraySpeed;
      this.spraySpeedVariance = spraySpeedVariance;
      this.SprayDirection = sprayDirection;
      this.sprayDirectionSpread = sprayDirectionSpread;
      this.emitTime = emitTime1;
      this.particleLifeTime = particleLifeTime;
      this.particleLifeTimeVariance = particleLifeTimeVariance;
      this.sprayThickness = sprayThickness;

      sprays = new ArrayList(sprayThickness * 20);

      random = new Random(System.DateTime.Now.Millisecond);

      //sprayThickness = 10000;
      if (sprayThickness <= 1)
        sprayThickness = 1;
      maxToMakePerSecond = 1000 / sprayThickness;

      AgateLib.Geometry.Color c = new AgateLib.Geometry.Color();
      c.R = (byte)red;
      c.G = (byte)green;
      c.B = (byte)blue;
      c.A = (byte)100;

      mySprite.ColorGradient = new AgateLib.Geometry.Gradient(c);
    }

    public override void Update(int delta) {
      base.Update(delta);
      // go throught each entity, if an entity dosent exist at the position create one if lifetime isent expired.
      TotalLife += delta;

      // if the sprayertime is over make it stop spraying..
      if ((TotalLife > emitTime) && emitTime > 0) {
        sprayerOn = false;
        CollisionDamage = 0;
      }

      if (sprayerOn) {
        int numEntitiesToMakeThisRound = (sprayThickness * delta);
        // need to be able to set emitting thickness per 1000ms
        // to much performance reduction with method of minimum 1 per 1ms
        // deltaSinceLastMake // maxToMakePerSecond

        for (int i = 0; i < numEntitiesToMakeThisRound; i++) {
          double speed = spraySpeed + (spraySpeedVariance / 2) - (random.NextDouble() * spraySpeedVariance);
          double direction = SprayDirection + (sprayDirectionSpread / 2) - (random.NextDouble() * sprayDirectionSpread);
          int lifetime = particleLifeTime + (particleLifeTimeVariance / 2) - (random.Next(particleLifeTimeVariance));
          sprays.Add(new Entity(mySprite.Clone(), (int)this.X, (int)this.Y, speed, direction, this.Radius, (int)this.CollisionDamage, lifetime, this.myState));
        }
      }

      for (int i = 0; i < sprays.Count; i++) {
        EntityAbstract e = (EntityAbstract)sprays[i];
        if (e.TotalLife > e.LifeTime) {
          sprays.RemoveAt(i);
        }
        else {
          e.Update(delta);
        }
      }

      if (sprays.Count == 0) {
        done = true;
      }
    }

    public override void Draw() {
      for (int i = 0; i < sprays.Count; i++) {
        EntityAbstract e = (EntityAbstract)sprays[i];
        e.Draw();
      }
    }

    public override void Collide(EntityAbstract e) {
      //we do nothing if this collides, explosions dont take damage....
    }
  }
}
